/*
 * @Author: 李石
 * @Date: 2024-05-18 10:34:24
 * @LastEditors: lishi
 * @LastEditTime: 2024-05-22 18:58:16
 * @Description: 
 * Copyright (c) 2024 by ${lishi0105@163.com}, All Rights Reserved. 
 */
#include <arpa/inet.h>
#include "HttpData.hpp"
#include <nlohmann/json.hpp>

HttpData::Ptr HttpData::CreateShared(struct mg_connection *c,struct mg_http_message *hm) {
    return std::make_shared<HttpData>(c,hm);
}

HttpData::HttpData(struct mg_connection *c,struct mg_http_message *hm):
    m_vaild(true),
    http_content_len(0),
    http_remote_port(0),
    http_err_msg(""),
    http_uri(""),
    http_method(""),
    http_remote_ip(""),
    http_content_type("N/A"),
    http_body("")

{
    if (c == nullptr || hm == nullptr) {
        std::cerr<<"HttpData::CreateShared: invalid input"<<std::endl;
        return;
    }
    char tmp_buf[256] = {0};
    if(hm->method.len > 0 && (hm->method.len < sizeof(tmp_buf) - 1)){
        memcpy(tmp_buf, hm->method.buf, hm->method.len);
        tmp_buf[hm->method.len] = '\0';
        http_method = std::string(tmp_buf);
        if(strstr(http_method.c_str(), "POST")){
            http_method = std::string("POST");
        }else if(strstr(http_method.c_str(), "GET")){
            http_method = std::string("GET");
        }else{
            std::cout<<"["<<http_method<<"] only support POST or GET"<<std::endl;
            m_vaild = false;
        }
    }else{
        m_vaild = false;
    }
    if(hm->uri.len > 0 && (hm->uri.len < sizeof(tmp_buf) - 1)){
        memcpy(tmp_buf, hm->uri.buf, hm->uri.len);
        tmp_buf[hm->uri.len] = '\0';
        http_uri = std::string(tmp_buf);
    }else{
        m_vaild = false;
    }
    char ip_str[INET6_ADDRSTRLEN]; // buffer to hold the IP address
    memset(ip_str, 0, sizeof(ip_str));
    if (c->rem.is_ip6) {
        // Convert IPv6 address from binary to text form
        if (inet_ntop(AF_INET6, c->rem.ip, ip_str, sizeof(ip_str)) == NULL) {
            perror("inet_ntop failed for IPv6");
            m_vaild = false;
            return;
        }
    } else {
        // Convert IPv4 address from binary to text form
        // Note: Only the first 4 bytes of addr->ip are used for IPv4
        if (inet_ntop(AF_INET, c->rem.ip, ip_str, sizeof(ip_str)) == NULL) {
            perror("inet_ntop failed for IPv4");
            m_vaild = false;
            return;
        }
    }
    http_remote_ip = std::string(ip_str);
    http_remote_port = c->rem.port;
    struct mg_str *h = mg_http_get_header(hm, "Content-Type");
    if (h != nullptr) {
        if(h->len > 0 && (h->len < sizeof(tmp_buf) - 1)){
            memcpy(tmp_buf, h->buf, h->len);
            tmp_buf[h->len] = '\0';
            http_content_type = std::string(tmp_buf);
        }else{
            m_vaild = false;
        }
    }
    if(http_content_type.empty()){
        http_content_type = std::string("N/A");
    }
    http_content_len = hm->body.len;
    if(hm->body.len > 0 && (hm->body.len < sizeof(tmp_buf) - 1)){
        memcpy(tmp_buf, hm->body.buf, hm->body.len);
        tmp_buf[hm->body.len] = '\0';
        http_body = std::string(tmp_buf);
    }
}

const std::string HttpData::to_string(bool pretty) const 
{
    try{
        nlohmann::json j;
        j["method"] = http_method;
        j["uri"] = http_uri;
        j["remote_ip"] = http_remote_ip;
        j["remote_port"] = http_remote_port;
        j["content_type"] = http_content_type;
        j["content_len"] = http_content_len;
        j["body"] = http_body;
        j["valid"] = m_vaild;
        
        if(pretty){
            return j.dump(4);
        }
        return j.dump();
    }catch(const nlohmann::json::type_error& e){
        std::cerr<<e.what()<<std::endl;
    }
    return "";
}